package com.dpj.wait_test;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import java.util.Set;

@Slf4j(topic = "c.GuardedObjectDemo")
public class GuardedObjectDemo {
    public static void main(String[] args) {


    }


}
@Slf4j(topic = "c.People")
class People extends Thread{
    @SneakyThrows
    @Override
    public void run() {
        //送信
        GuarddeObject1 guardedObject = Mailboxes.createGuardedObject();
        //收信
        log.debug("开始收信id:{}", guardedObject.getId());
        Object mail = guardedObject.get(1000);
        log.debug("收到信id:{},内容:{}",guardedObject.getId(),mail);

    }
}
@Slf4j(topic = "c.Postman")
class Postman extends Thread {
    private int id;
    private String mail;
    public Postman(int id,String mail){
        this.id=id;
        this.mail=mail;
    }
    @Override
    public void run() {
        GuarddeObject1 guarddeObject = Mailboxes.getGuarddeObject(id);
        log.debug("开始送信id:{},内容:{}", id,mail);
        guarddeObject.complete(mail);
    }
}
@Slf4j(topic = "c.Mailboxes")
class Mailboxes{
    private  static  Map<Integer,GuarddeObject1> boxes=new Hashtable<>();
    private  static  int id=1;
    //产生唯一id
    private  static  synchronized int generateId(){
        return  id++;
    }

    public static GuarddeObject1 createGuardedObject(){
        GuarddeObject1 go=new GuarddeObject1(generateId());
        boxes.put(go.getId(),go);
        return go;
    }

    public static GuarddeObject1 getGuarddeObject(int id){
        return boxes.remove(id);

    }

    public static Set<Integer> getIds(){
        return boxes.keySet();
    }
}

//增加超时结果
class GuarddeObject1{

    //标识 GuarddeObject1
    private int id;

    public int getId() {
        return id;
    }

    public GuarddeObject1(int id) {
        this.id = id;
    }

    public void setId(int id) {
        this.id = id;
    }

    //结果
    private  Object response;
    //获取结果
    public Object get(long timeout) throws InterruptedException {
         synchronized (this){
             //开始时间
             long start = System.currentTimeMillis();
             //经历时间
             long passedTime=0;

             while(response==null){
                 //经历的时间超过了最大等待时间，退出循环
                 if(passedTime>timeout){
                     break;
                 }
                 this.wait(timeout-passedTime);//防止虚假唤醒
                 //求得经历的时间
                 passedTime=System.currentTimeMillis()-start;
             }
             return response;
         }
    }

    //生成结果
    public void complete(Object object){
        synchronized (this){
            //给结果变量赋值
            this.response=object;
            this.notifyAll();

        }
    }

}
